﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using Avivo.Common;

namespace Avivo.Tools.Sprite
{
	internal static class Converter
	{
		public static ILogger Logger = new ConsoleLogger();

		#region Shortcuts
		public static bool XamlToBitmap(string sourcePath, string targetPath)
		{
			return XamlToImage<BmpBitmapEncoder>(sourcePath, targetPath);
		}

		public static bool XamlToJpeg(string sourcePath, string targetPath)
		{
			return XamlToImage<JpegBitmapEncoder>(sourcePath, targetPath);
		}

		public static bool XamlToGif(string sourcePath, string targetPath)
		{
			return XamlToImage<GifBitmapEncoder>(sourcePath, targetPath);
		}

		public static bool XamlToPng(string sourcePath, string targetPath)
		{
			return XamlToImage<PngBitmapEncoder>(sourcePath, targetPath);
		}

		public static bool XamlToTiff(string sourcePath, string targetPath)
		{
			return XamlToImage<TiffBitmapEncoder>(sourcePath, targetPath);
		}

		public static bool XamlToWmp(string sourcePath, string targetPath)
		{
			return XamlToImage<WmpBitmapEncoder>(sourcePath, targetPath);
		}
		#endregion

		#region Converters
		/// <summary>
		/// Converts a .xaml file to a raster image file. Target format is defined with the specified encoder.
		/// </summary>
		/// <param name="sourceFilename"></param>
		/// <param name="destFilename"></param>
		public static bool XamlToImage<TEncoder>(string sourceFilename, string targetFilename) where TEncoder : BitmapEncoder, new()
		{
			bool result = false;

			using (XmlTextReader xmlReader = new XmlTextReader(sourceFilename))
			{
				const int dpi = 96;

				//Load xaml
				Panel container = (Panel)XamlReader.Load(xmlReader);
				Logger.WriteLine("Xaml loaded: " + sourceFilename);

				#region Set target dimensions
				//Width must be set when alignment is 'Center', 'Right', or 'Stretch'
				if (double.IsNaN(container.Width) && container.HorizontalAlignment != HorizontalAlignment.Left)
				{
					container.HorizontalAlignment = HorizontalAlignment.Left;
				}
				if (double.IsNaN(container.Height) && container.VerticalAlignment != VerticalAlignment.Top)
				{
					container.VerticalAlignment = VerticalAlignment.Top;
				}

				//Arrange max size to get real ActualWidth and ActualHeight values
				container.Arrange(new Rect(0, 0, int.MaxValue, int.MaxValue));

				int width = (int)container.ActualWidth;
				int height = (int)container.ActualHeight;

				//Arrange to target size
				container.Arrange(new Rect(0, 0, width, height));
				Logger.WriteLine(string.Format("Dimensions: {0}x{1}", width, height));
				#endregion

				//Render to bitmap
				RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(width, height, dpi, dpi, PixelFormats.Default);
				renderTargetBitmap.Render(container);
				Logger.WriteLine("Rendered to bitmap.");

				//Encode to the specified format
				TEncoder bitmapEncoder = new TEncoder();
				bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
				Logger.WriteLine("Encoding completed.");

				//Save to a file
				using (FileStream fileStream = new FileStream(targetFilename, FileMode.Create))
				{
					bitmapEncoder.Save(fileStream);
					Logger.WriteLine("File saved: " + targetFilename);
				}

				result = File.Exists(targetFilename);
			}

			//Clear garbage collector
			GC.Collect();
			GC.WaitForPendingFinalizers();

			return result;
		}
		#endregion
	}
}
